package com.cq.hd.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.entity.hf.HfInvApply;
import com.cq.hd.common.entity.hf.HfInvApplyBatch;
import com.cq.hd.common.enums.biz.OrderSettleBillInvoiceStatusEnum;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeStateEnum;
import com.cq.hd.common.enums.biz.OrderSettleBillTradeTypeEnum;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.GenerateUtil;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.order.mapper.TbInvoiceItemRecordMapper;
import com.cq.hd.order.mapper.TbOrderSettleBillMapper;
import com.cq.hd.order.po.TbInvoiceItemRecordPo;
import com.cq.hd.order.po.TbInvoiceRecordPo;
import com.cq.hd.order.mapper.TbInvoiceRecordMapper;
import com.cq.hd.order.po.TbOrderSettleBillPo;
import com.cq.hd.order.service.TbInvoiceRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.system.api.HfApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 发票记录表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2024-02-18
 */
@Slf4j
@Service
public class TbInvoiceRecordServiceImpl extends ServiceImpl<TbInvoiceRecordMapper, TbInvoiceRecordPo> implements TbInvoiceRecordService {

    @Autowired
    private TbOrderSettleBillMapper orderSettleBillMapper;

    @Autowired
    private TbInvoiceItemRecordMapper invoiceItemRecordMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private HfApi hfApi;

    @Override
    public Boolean invoiceAgentAmtJob() {
        LocalDate beforeLocalDate = LocalDate.now().plusMonths(-1);
        String firstDayOfMonthStartStr = LocalDateUtil.toLocalDateToString(beforeLocalDate.with(TemporalAdjusters.firstDayOfMonth()), Constant.YYYY_MM_DD) + " 00:00:00";
        String lastDayOfMonthEndStr = LocalDateUtil.toLocalDateToString(beforeLocalDate.with(TemporalAdjusters.lastDayOfMonth()), Constant.YYYY_MM_DD) + " 23:59:59";

        // 扫描tb_order_settle_bill表,获取上个月支付成功的未开票的佣金数据
        //			获取列表数据的req_date和req_seq_id作为发票的交易流水列表字段
        List<TbOrderSettleBillPo> orderSettleBillPos = orderSettleBillMapper.selectList(new QueryWrapper<TbOrderSettleBillPo>().eq("del_state", 0)
                .eq("trade_type", OrderSettleBillTradeTypeEnum.COMMISSION_AMT.getValue())
                .eq("trade_state", OrderSettleBillTradeStateEnum.SUCCESS.getValue())
                .eq("invoice_status", OrderSettleBillInvoiceStatusEnum.NO.getValue())
                .ge("trade_time", firstDayOfMonthStartStr)
                .le("trade_time", lastDayOfMonthEndStr));
        if (CollectionUtils.isEmpty(orderSettleBillPos)) {
            return true;
        }

        List<HfInvApplyBatch> hfInvApplyBatches = new ArrayList<>();

        for (TbOrderSettleBillPo orderSettleBillPo : orderSettleBillPos) {
            String reqSeqId = orderSettleBillPo.getReqSeqId();
            String reqDate = orderSettleBillPo.getReqDate();
            if (StringUtils.isEmpty(reqSeqId) || StringUtils.isEmpty(reqDate)) {
                continue;
            }

            HfInvApplyBatch hfInvApplyBatch = new HfInvApplyBatch();
            hfInvApplyBatch.setOrderSettleBillId(orderSettleBillPo.getId());
            hfInvApplyBatch.setTransDate(reqDate);
            hfInvApplyBatch.setTransSeqId(reqSeqId);
            hfInvApplyBatches.add(hfInvApplyBatch);
        }

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);

        HfInvApply hfInvApply = new HfInvApply();
        hfInvApply.setReqSeqId(reqSeqId);
        hfInvApply.setReqDate(yyyyMMdd);
        hfInvApply.setBatchList(hfInvApplyBatches);
        HfInvApply hfInvApplyResult = hfApi.hycInvApply(hfInvApply).unpack();
        if (hfInvApplyResult != null && !StringUtils.isEmpty(hfInvApplyResult.getResult())) {
            String invoiceBatch = hfInvApplyResult.getInvoiceBatch();
            if (!StringUtils.isEmpty(invoiceBatch)) {
                saveData(nowLocalDateTime, hfInvApplyResult);
            }
        }
        return true;
    }

    public void saveData(LocalDateTime nowLocalDateTime, HfInvApply hfInvApply) {
        String invoiceBatch = hfInvApply.getInvoiceBatch();
        List<HfInvApplyBatch> hfInvApplyBatches = hfInvApply.getBatchList();


        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            // 新增开票记录数据
            TbInvoiceRecordPo tbInvoiceRecordPo = new TbInvoiceRecordPo();
            tbInvoiceRecordPo.setReqSeqId(hfInvApply.getReqSeqId());
            tbInvoiceRecordPo.setReqDate(hfInvApply.getReqDate());
            tbInvoiceRecordPo.setReceiveMobile(hfInvApply.getReceiveMobile());
            tbInvoiceRecordPo.setReceiveName(hfInvApply.getReceiveName());
            tbInvoiceRecordPo.setCourierAddress(hfInvApply.getCourierAddress());
            tbInvoiceRecordPo.setInvoiceCategory(hfInvApply.getInvoiceCategory());
            tbInvoiceRecordPo.setInvoiceType(hfInvApply.getInvoiceType());
            tbInvoiceRecordPo.setInvoiceBatch(invoiceBatch);
            tbInvoiceRecordPo.setCreateTime(nowLocalDateTime);
            tbInvoiceRecordPo.setUpdateTime(nowLocalDateTime);
            int insert = baseMapper.insert(tbInvoiceRecordPo);
            if (insert <= 0) {
                log.error("新增开票记录数据失败, orderSettleBillId:{}", JSON.toJSONString(tbInvoiceRecordPo));
                Throw.isBusinessException("新增开票记录数据失败");
            }
            Long invoiceId = tbInvoiceRecordPo.getId();


            for (HfInvApplyBatch hfInvApplyBatch : hfInvApplyBatches) {
                Long orderSettleBillId = hfInvApplyBatch.getOrderSettleBillId();
                // 更新开票状态
                insert = orderSettleBillMapper.updateInvoiceStatusById(orderSettleBillId, OrderSettleBillInvoiceStatusEnum.YES.getValue());
                if (insert <= 0) {
                    log.error("更新开票状态失败, orderSettleBillId:{}", orderSettleBillId);
                    Throw.isBusinessException("更新开票状态失败");
                }

                // 新增发票交易记录
                TbInvoiceItemRecordPo tbInvoiceItemRecordPo = new TbInvoiceItemRecordPo();
                tbInvoiceItemRecordPo.setInvoiceId(invoiceId);
                tbInvoiceItemRecordPo.setReqSeqId(hfInvApplyBatch.getTransSeqId());
                tbInvoiceItemRecordPo.setReqDate(hfInvApplyBatch.getTransDate());
                tbInvoiceItemRecordPo.setOrderSettleBillId(hfInvApplyBatch.getOrderSettleBillId());
                tbInvoiceItemRecordPo.setCreateTime(nowLocalDateTime);
                tbInvoiceItemRecordPo.setUpdateTime(nowLocalDateTime);
                insert = invoiceItemRecordMapper.insert(tbInvoiceItemRecordPo);
                if (insert <= 0) {
                    log.error("新增发票交易记录数据失败, orderSettleBillId:{}", JSON.toJSONString(tbInvoiceItemRecordPo));
                    Throw.isBusinessException("新增发票交易记录数据失败");
                }
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<定时开票任务>事务异常回滚", e);
            Throw.isBusinessException(e.getMessage());
        }
    }
}
